package org.jeecg.modules.business.outbound.service.impl;

import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.BeanUtil;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceipt;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceiptLoadCheck;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceiptMaterial;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptLoadCheckService;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptMaterialService;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptService;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTask;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskMaterial;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskPick;
import org.jeecg.modules.business.outbound.entity.vo.*;
import org.jeecg.modules.business.outbound.mapper.WmsOutReceiptTaskPickMapper;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskMaterialService;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskPickService;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskService;
import org.jeecg.modules.business.outbound.vo.WmsOutReceiptTaskMaterialResponseVO;
import org.jeecg.modules.business.repertory.entity.WmsRepertory;
import org.jeecg.modules.business.repertory.service.IWmsRepertoryService;
import org.jeecg.modules.business.transfer.entity.WmsMoveReceiptMaterial;
import org.jeecg.modules.business.transfer.vo.WmsMoveReceiptPage;
import org.jeecg.modules.flow.callback.delivery.util.CommonDeliveryTaskUtil;
import org.jeecg.modules.flow.callback.enums.DocumentStatusEnum;
import org.jeecg.modules.flow.callback.enums.OutboundStatusEnum;
import org.jeecg.modules.flow.callback.enums.SimpleDocumentTypeEnum;
import org.jeecg.modules.flow.callback.outbound.util.CommonOutboundUtil;
import org.jeecg.modules.flow.record.entity.WmsFlowRecord;
import org.jeecg.modules.flow.sys.entity.dto.BaseFlowDto;
import org.jeecg.modules.flow.sys.entity.dto.WorkFlowInfoDto;
import org.jeecg.modules.flow.sys.service.WorkFlowService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 出库任务-拣货
 * @Author: jeecg-boot
 * @Date:   2023-08-09
 * @Version: V1.0
 */
@RequiredArgsConstructor
@Service
public class WmsOutReceiptTaskPickServiceImpl extends ServiceImpl<WmsOutReceiptTaskPickMapper, WmsOutReceiptTaskPick> implements IWmsOutReceiptTaskPickService {


    private final WmsOutReceiptTaskPickMapper pickMapper;

    private final IWmsOutReceiptTaskService taskService;

    private final IWmsOutReceiptTaskMaterialService taskMaterialService;

    private final IWmsOutReceiptService receiptService;

    private final IWmsOutReceiptMaterialService receiptMaterialService;

    @Lazy
    private final CommonOutboundUtil commonOutboundUtil;

    private final CommonDeliveryTaskUtil commonDeliveryTaskUtil;

    private final WorkFlowService workFlowService;

    private final IWmsOutReceiptLoadCheckService loadCheckService;

    private final IWmsRepertoryService repertoryService;


    /**
     * 查询所有未拣货信息
     * @param taskId
     * @param materialName
     * @param batchCode
     * @return
     */
    @Override
    public IPage<OutboundTaskUnPickVO> listAllUnPick(IPage<WmsOutReceiptTaskPick> page, String taskId, String materialName, String batchCode, String deviceType) {

        IPage<OutboundTaskUnPickVO> pageList= pickMapper.listAllUnPick(page,taskId, materialName, batchCode,deviceType);
        List<OutboundTaskUnPickVO> list = pageList.getRecords();
        if(!CollectionUtil.isEmpty(list)){
            for(OutboundTaskUnPickVO fullVO:list){
                // 查询即时库存中的库区库位
                RepertorySimpleVO repertorySimpleVO = taskService.getMaterialRepertoryInfoByOutId(fullVO.getWmsOutReceiptTaskMaterialId());
                fullVO.setWmsBasicWarehouseId(repertorySimpleVO.getWmsBasicWarehouseId());
                fullVO.setWmsBasicWarehouseName(repertorySimpleVO.getWmsBasicWarehouseName());
                fullVO.setWmsBasicWarehouseAreaId(repertorySimpleVO.getWmsBasicWarehouseAreaId());
                fullVO.setWmsBasicWarehouseAreaName(repertorySimpleVO.getWmsBasicWarehouseAreaName());
                fullVO.setWmsBasicWarehouseAreaLocationId(repertorySimpleVO.getWmsBasicWarehouseAreaLocationId());
                fullVO.setWmsBasicWarehouseAreaLocationName(repertorySimpleVO.getWmsBasicWarehouseAreaLocationName());
            }
            pageList.setRecords(list);
            return pageList;
        }else{
            return pageList;
        }
    }

    /**
     * 查询所有已拣货信息
     * @param taskId
     * @param materialName
     * @param batchCode
     * @return
     */
    @Override
    public IPage<OutboundTaskPickVO> listAllPicked(IPage<WmsOutReceiptTaskPick> page,String taskId, String materialName, String batchCode) {
        IPage<OutboundTaskPickVO> pageList=pickMapper.listPageAllPicked(page,taskId, materialName, batchCode);
        return pageList;
    }

    /**
     * 查询所有已拣货信息(全)
     * @param taskId
     * @return
     */
    @Override
    public List<OutboundTaskFullPickVO> listAllFullPicked(String taskId,Boolean unCompleted,Boolean pdaFilterFlag) {
        List<OutboundTaskPickVO> list= pickMapper.listAllPicked(taskId, null,null);
        if(CollectionUtil.isEmpty(list)){
            return Collections.emptyList();
        }else{
            List<OutboundTaskFullPickVO> collect = list.stream().map(pickVO -> {
                OutboundTaskFullPickVO outboundTaskFullPickVO = new OutboundTaskFullPickVO();
                WmsOutReceiptTaskMaterial taskMaterial = taskMaterialService.getById(pickVO.getWmsOutReceiptTaskMaterialId());
                if (!Objects.isNull(taskMaterial)) {
                    cn.hutool.core.bean.BeanUtil.copyProperties(taskMaterial, outboundTaskFullPickVO);
                }
                cn.hutool.core.bean.BeanUtil.copyProperties(pickVO, outboundTaskFullPickVO);
                return outboundTaskFullPickVO;
            }).collect(Collectors.toList());
            if(!Objects.isNull(unCompleted)&&unCompleted){
                //将已完成的过滤掉
                collect=collect.stream().filter(o-> !OutboundStatusEnum.ALL.getCode().equals(o.getOutboundStatus())).collect(Collectors.toList());
            }
            if(!Objects.isNull(pdaFilterFlag)&&pdaFilterFlag){
                //将在出库单中保存的过滤掉
                List<WmsOutReceiptMaterial> receiptMaterialList=receiptService.getReceiptMaterialByTaskId(taskId);
                if(!CollectionUtil.isEmpty(receiptMaterialList)){
                    Map<String, List<WmsOutReceiptMaterial>> listMap = receiptMaterialList.stream().collect(Collectors.groupingBy(WmsOutReceiptMaterial::getWmsOutReceiptTaskMaterialId));
                    //找出出库单中需要过滤的物料数据
                    Map<String,BigDecimal> needFilterMap=new HashMap<>(16);
                    if(!CollectionUtil.isEmpty(listMap)){
                        listMap.forEach((taskMaterialId,tempList)->{
                            if(!StrUtil.isEmpty(taskMaterialId)){
                                if(!CollectionUtil.isEmpty(tempList)){
                                    BigDecimal addResult = tempList.stream().map(o->
                                            Objects.isNull(o.getOutboundQuantity())?BigDecimal.ZERO:o.getOutboundQuantity()
                                    ).reduce(BigDecimal.ZERO, BigDecimal::add);
                                    needFilterMap.put(taskMaterialId,addResult);
                                }
                            }
                        });
                    }
                    if(!CollectionUtil.isEmpty(needFilterMap)){
                        collect=collect.stream().filter(o->{
                            if(needFilterMap.containsKey(o.getWmsOutReceiptTaskMaterialId())){
                                BigDecimal addResult = needFilterMap.get(o.getWmsOutReceiptTaskMaterialId());
                                if(addResult.compareTo(o.getPickQuantity())<0){
                                    return true;
                                }else{
                                    return false;
                                }
                            }else{
                                return true;
                            }
                        }).collect(Collectors.toList());
                    }
                }
            }
            return collect;
        }
    }

    /**
     * 查询所有已拣货信息(全)-pda用
     * @param pdaPickReqVO
     * @return
     */
    @Override
    public List<OutboundTaskFullPickVO> pdaListAllFullPicked(PdaPickReqVO pdaPickReqVO) {
        String taskId = pdaPickReqVO.getTaskId();
        Boolean unCompleted=pdaPickReqVO.getUnCompleted();
        Boolean pdaFilterFlag =pdaPickReqVO.getPdaFilterFlag();
        String batchCode =pdaPickReqVO.getBatchCode();
        List<OutboundTaskPickVO> list= pickMapper.listAllPicked(taskId, null,batchCode);
        if(CollectionUtil.isEmpty(list)){
            return Collections.emptyList();
        }else{
            List<OutboundTaskFullPickVO> collect = list.stream().map(pickVO -> {
                OutboundTaskFullPickVO outboundTaskFullPickVO = new OutboundTaskFullPickVO();
                WmsOutReceiptTaskMaterial taskMaterial = taskMaterialService.getById(pickVO.getWmsOutReceiptTaskMaterialId());
                if (!Objects.isNull(taskMaterial)) {
                    cn.hutool.core.bean.BeanUtil.copyProperties(taskMaterial, outboundTaskFullPickVO);
                }
                cn.hutool.core.bean.BeanUtil.copyProperties(pickVO, outboundTaskFullPickVO);
                return outboundTaskFullPickVO;
            }).collect(Collectors.toList());
            if(!Objects.isNull(unCompleted)&&unCompleted){
                //将已完成的过滤掉
                collect=collect.stream().filter(o-> !OutboundStatusEnum.ALL.getCode().equals(o.getOutboundStatus())).collect(Collectors.toList());
            }
            if(!Objects.isNull(pdaFilterFlag)&&pdaFilterFlag){
                //将在出库单中保存的过滤掉
                List<WmsOutReceiptMaterial> receiptMaterialList=receiptService.getReceiptMaterialByTaskId(taskId);
                if(!CollectionUtil.isEmpty(receiptMaterialList)){
                    Map<String, List<WmsOutReceiptMaterial>> listMap = receiptMaterialList.stream().collect(Collectors.groupingBy(WmsOutReceiptMaterial::getWmsOutReceiptTaskMaterialId));
                    //找出出库单中需要过滤的物料数据
                    Map<String,BigDecimal> needFilterMap=new HashMap<>(16);
                    if(!CollectionUtil.isEmpty(listMap)){
                        listMap.forEach((taskMaterialId,tempList)->{
                            if(!StrUtil.isEmpty(taskMaterialId)){
                                if(!CollectionUtil.isEmpty(tempList)){
                                    BigDecimal addResult = tempList.stream().map(o->
                                            Objects.isNull(o.getOutboundQuantity())?BigDecimal.ZERO:o.getOutboundQuantity()
                                    ).reduce(BigDecimal.ZERO, BigDecimal::add);
                                    needFilterMap.put(taskMaterialId,addResult);
                                }
                            }
                        });
                    }
                    if(!CollectionUtil.isEmpty(needFilterMap)){
                        collect=collect.stream().filter(o->{
                            if(needFilterMap.containsKey(o.getWmsOutReceiptTaskMaterialId())){
                                BigDecimal addResult = needFilterMap.get(o.getWmsOutReceiptTaskMaterialId());
                                if(addResult.compareTo(o.getPickQuantity())<0){
                                    return true;
                                }else{
                                    return false;
                                }
                            }else{
                                return true;
                            }
                        }).collect(Collectors.toList());
                    }
                }
            }
            if(!CollectionUtil.isEmpty(collect)){
                for(OutboundTaskFullPickVO fullPickVO:collect){
                    RepertorySimpleVO repertorySimpleVO = taskService.getMaterialRepertoryInfoByOutId(fullPickVO.getId());
                    fullPickVO.setWmsBasicWarehouseId(repertorySimpleVO.getWmsBasicWarehouseId());
                    fullPickVO.setWmsBasicWarehouseAreaId(repertorySimpleVO.getWmsBasicWarehouseAreaId());
                    fullPickVO.setWmsBasicWarehouseAreaLocationId(repertorySimpleVO.getWmsBasicWarehouseAreaLocationId());
                }
                List<String> warehouseAreaIdList = pdaPickReqVO.getWarehouseAreaIdList();
                //根据传入库区进行筛选
                if(!CollectionUtil.isEmpty(warehouseAreaIdList)){
                    collect=collect.stream().filter(o->CollectionUtil.contains(warehouseAreaIdList,o.getWmsBasicWarehouseAreaId())).collect(Collectors.toList());
                }
            }
            return collect;
        }
    }

    /**
     * 分页查询所有已拣货信息(全)
     * @param page
     * @param taskId
     * @return
     */
    @Override
    public IPage<OutboundTaskFullPickVO> listPageAllFullPicked(IPage<WmsOutReceiptTaskPick> page, String taskId) {
        IPage<OutboundTaskFullPickVO> pageList=pickMapper.listPageAllFullPicked(page,taskId);
        List<OutboundTaskFullPickVO> list = pageList.getRecords();
        if(!CollectionUtil.isEmpty(list)){
            List<OutboundTaskFullPickVO> finalList=new ArrayList<>();
            for(OutboundTaskFullPickVO pickVO:list){
                OutboundTaskFullPickVO fullPickVO=new OutboundTaskFullPickVO();
                WmsOutReceiptTaskMaterial taskMaterial = taskMaterialService.getById(pickVO.getWmsOutReceiptTaskMaterialId());
                if(!Objects.isNull(taskMaterial)){
                    cn.hutool.core.bean.BeanUtil.copyProperties(taskMaterial,fullPickVO);
                }
                cn.hutool.core.bean.BeanUtil.copyProperties(pickVO,fullPickVO, CopyOptions.create().setIgnoreNullValue(true));
                finalList.add(fullPickVO);
            }
            pageList.setRecords(finalList);
        }
        return pageList;
    }

    /**
     * 获取拣货编号
     * @param taskId
     * @return
     */
    @Override
    public String getPickCode(String taskId) {

        WmsOutReceiptTaskPick newestOne=this.baseMapper.getNewestRecordIgnoreDelete(taskId);
        if(Objects.isNull(newestOne)){
            return "1";
        }else{
            String pickCode = newestOne.getPickCode();
            int parseInt = Integer.parseInt(pickCode);
            return parseInt+1+"";
        }
    }

    /**
     * 增加拣货信息
     * @param addPickVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addPickInfo(OutboundTaskAddPickVO addPickVO) {
        WmsOutReceiptTask wmsOutReceiptTask = taskService.getById(addPickVO.getWmsOutReceiptTaskId());
        if(Objects.isNull(wmsOutReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }
        Boolean needPickFlag = commonOutboundUtil.needPickFlag(addPickVO.getWmsOutReceiptTaskId());
        if(!needPickFlag){
            throw new JeecgBootException("该任务不能拣货");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceiptTask.getDocumentStatus())){
            throw new JeecgBootException("该任务已经完成");
        }
        List<OutboundTaskPickInfoVO> pickInfoVOList = addPickVO.getPickInfoVOList();
        //校验拣货信息是否有仓库库区库位
        List<String> batchCodes = pickInfoVOList.stream().filter(o -> StrUtil.isEmpty(o.getWmsBasicWarehouseId()))
                .map(OutboundTaskPickInfoVO::getBatchCode).collect(Collectors.toList());
        if (batchCodes.size() > 0) {
            throw new JeecgBootException("存在拣货信息在即时库存中查询不到, 批次号为: " + batchCodes);
        }
        //检验拣货数量是否小于即时库存的可用量
        for(OutboundTaskPickInfoVO pickInfoVO:pickInfoVOList){
            String materialName=pickInfoVO.getMaterialName();
            if(!StrUtil.isEmpty(pickInfoVO.getBatchCode())){
                materialName+=(",批次号为"+pickInfoVO.getBatchCode());
            }
            BigDecimal pickQuantity = pickInfoVO.getPickQuantity();
            //根据拣货信息查询即时库存中的信息
            LambdaQueryWrapper<WmsRepertory> queryWrapper=new LambdaQueryWrapper<WmsRepertory>();
            if(!StrUtil.isEmpty(pickInfoVO.getWmsBasicWarehouseId())){
                queryWrapper.eq(WmsRepertory::getWmsBasicWarehouseId,pickInfoVO.getWmsBasicWarehouseId());
            }
            if(!StrUtil.isEmpty(pickInfoVO.getBatchCode())){
                queryWrapper.eq(WmsRepertory::getBatchCode,pickInfoVO.getBatchCode());
            }else if(!StrUtil.isEmpty(pickInfoVO.getWmsBasicMaterialId())){
                queryWrapper.eq(WmsRepertory::getMaterialId,pickInfoVO.getWmsBasicMaterialId());
            }else{
                throw new JeecgBootException("存在拣货信息在即时库存中查询不到,"+materialName);
            }
            queryWrapper.last("LIMIT 1");
            WmsRepertory repertory = repertoryService.getOne(queryWrapper);
            if(!Objects.isNull(repertory)){
                BigDecimal usableQuantity = repertory.getUsableQuantity();
                if(pickQuantity.compareTo(usableQuantity)>0){

                    String errorMessage= materialName+"拣货数量大于即时库存中的可用量，可用量为"+usableQuantity;
                    throw new JeecgBootException(errorMessage);
                }
            }else{
                throw new JeecgBootException("存在拣货信息在即时库存中查询不到,"+materialName);
            }
        }
        List<WmsOutReceiptTaskPick> pickList = BeanUtil.copyToList(pickInfoVOList, WmsOutReceiptTaskPick.class);
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String loginUserUsername = loginUser.getUsername();
        pickList.stream().forEach(p->{
            p.setPickPerson(loginUserUsername);
            p.setPickTime(new Date());
            p.setHasOutboundQuantity(BigDecimal.ZERO);
        });
        //先保存拣货信息
        this.saveBatch(pickList);
        //更新任务物料的已拣货数量
        pickList.stream().forEach(p->{
            taskMaterialService.update(new LambdaUpdateWrapper<WmsOutReceiptTaskMaterial>()
                    .set(WmsOutReceiptTaskMaterial::getPickQuantity,p.getPickQuantity())
                    .eq(WmsOutReceiptTaskMaterial::getId,p.getWmsOutReceiptTaskMaterialId())
            );

        });
        //更新入库任务的状态为执行中
        taskService.update(new LambdaUpdateWrapper<WmsOutReceiptTask>()
                .set(WmsOutReceiptTask::getDocumentStatus,DocumentStatusEnum.PROCESS.getCode())
                .eq(WmsOutReceiptTask::getId,wmsOutReceiptTask.getId())
                .eq(WmsOutReceiptTask::getDocumentStatus,DocumentStatusEnum.COMMIT.getCode())
        );
        pickList.stream().forEach(p->{
            //更新调拨任务的物料状态
            commonDeliveryTaskUtil.updateMaterialDeliveryStatus(SimpleDocumentTypeEnum.OUT_TASK,p.getWmsOutReceiptTaskId(),p.getWmsOutReceiptTaskMaterialId(),"已拣货",null);
        });

    }


    /**
     * 取消拣货
     * @param cancelPickVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelPick(OutboundTaskCancelPickVO cancelPickVO) {

        WmsOutReceiptTask wmsOutReceiptTask = taskService.getById(cancelPickVO.getWmsOutReceiptTaskId());
        if(Objects.isNull(wmsOutReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }
        Boolean needPickFlag = commonOutboundUtil.needPickFlag(cancelPickVO.getWmsOutReceiptTaskId());
        if(!needPickFlag){
            throw new JeecgBootException("该任务不能拣货");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceiptTask.getDocumentStatus())){
            throw new JeecgBootException("该任务已经完成");
        }
        List<String> pickIdList = cancelPickVO.getPickInfoList().stream().map(CancelPickInfoVO::getId).collect(Collectors.toList());
        // 校验是否能取消拣货
        List<WmsOutReceiptTaskPick> pickList = this.listByIds(pickIdList);
        if(CollectionUtil.isEmpty(pickList)){
            return;
        }
        //检查物料是否已经出库
//        boolean anyMatch = pickList.stream().anyMatch(p -> BigDecimal.ZERO.compareTo(p.getHasOutboundQuantity()) != 0);
//        if(anyMatch){
//            throw new JeecgBootException("存在已经出库的物料，无法取消！");
//        }
        //判断物料是否在出库单中
        List<WmsOutReceipt> receiptList = receiptService.list(new LambdaQueryWrapper<WmsOutReceipt>()
                .eq(WmsOutReceipt::getWmsOutReceiptTaskId, cancelPickVO.getWmsOutReceiptTaskId())
        );
        if(!CollectionUtil.isEmpty(receiptList)){
            List<WmsOutReceiptMaterial> receiptMaterialList = receiptMaterialService.list(new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                    .in(WmsOutReceiptMaterial::getWmsOutReceiptId, receiptList.stream().map(WmsOutReceipt::getId).collect(Collectors.toList()))
            );
            for(WmsOutReceiptTaskPick pick:pickList){
                //用出库任务物料id进行匹配
                boolean anyMatch = receiptMaterialList.stream().anyMatch(o -> pick.getWmsOutReceiptTaskMaterialId().equals(o.getWmsOutReceiptTaskMaterialId()));
                if(anyMatch){
                    String errorMessage="已在出库的单中无法取消拣货，如需取消请从入库单中删除该物料";
                    errorMessage+=",该物料批次号为"+pick.getBatchCode();
                    throw new JeecgBootException(errorMessage);
                }
            }
        }
        // 检查物料是否装车复核
        Boolean needLoadCheckFlag = commonOutboundUtil.needLoadCheckFlag(cancelPickVO.getWmsOutReceiptTaskId());
        if(needLoadCheckFlag){
            // 检查装车复核数据
            for(WmsOutReceiptTaskPick pick:pickList){
                long existCount = loadCheckService.count(new LambdaQueryWrapper<WmsOutReceiptLoadCheck>()
                        .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptTaskId, pick.getWmsOutReceiptTaskId())
                        .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptTaskMaterialId, pick.getWmsOutReceiptTaskMaterialId())
                        .eq(WmsOutReceiptLoadCheck::getWmsBasicMaterialId, pick.getWmsBasicMaterialId())
                );
                if(existCount>0){
                    throw new JeecgBootException("存在装车复核的物料，无法取消");
                }
            }
        }
        // 取消拣货
        // 删除拣货数据
        this.removeByIds(pickIdList);
        // 更新任务物料的拣货数据

        for(WmsOutReceiptTaskPick pickPo:pickList){
            WmsOutReceiptTaskMaterial taskMaterial = taskMaterialService.getById(pickPo.getWmsOutReceiptTaskMaterialId());
            if(!Objects.isNull(taskMaterial)){
                BigDecimal subtract = taskMaterial.getPickQuantity().subtract(pickPo.getPickQuantity());
                if(BigDecimal.ZERO.compareTo(subtract)>0){
                    subtract=BigDecimal.ZERO;
                }
                taskMaterial.setPickQuantity(subtract);
                taskMaterialService.updateById(taskMaterial);
            }
        }
    }

    /**
     * 根据任务物料id取消拣货
     * @param cancelPickVO
     */
    @Override
    public void cancelPickByTaskMaterialId(OutboundTaskCancelPickByIdVO cancelPickVO) {
        WmsOutReceiptTask wmsOutReceiptTask = taskService.getById(cancelPickVO.getWmsOutReceiptTaskId());
        if(Objects.isNull(wmsOutReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }
        Boolean needPickFlag = commonOutboundUtil.needPickFlag(cancelPickVO.getWmsOutReceiptTaskId());
        if(!needPickFlag){
            throw new JeecgBootException("该任务不能拣货");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceiptTask.getDocumentStatus())){
            throw new JeecgBootException("该任务已经完成");
        }
        // 校验是否能取消拣货
        List<WmsOutReceiptTaskPick> pickList = this.list(new LambdaUpdateWrapper<WmsOutReceiptTaskPick>()
                .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskMaterialId,cancelPickVO.getWmsOutReceiptTaskMaterialId())
                .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskId,cancelPickVO.getWmsOutReceiptTaskId())
        );
        if(CollectionUtil.isEmpty(pickList)){
            return;
        }
//        //检查物料是否已经出库
//        boolean anyMatch = pickList.stream().anyMatch(p -> BigDecimal.ZERO.compareTo(p.getHasOutboundQuantity()) != 0);
//        if(anyMatch){
//            throw new JeecgBootException("存在已经出库的物料，无法取消！");
//        }
        //判断物料是否在出库单中
        List<WmsOutReceipt> receiptList = receiptService.list(new LambdaQueryWrapper<WmsOutReceipt>()
                .eq(WmsOutReceipt::getWmsOutReceiptTaskId, cancelPickVO.getWmsOutReceiptTaskId())
        );
        if(!CollectionUtil.isEmpty(receiptList)){
            List<WmsOutReceiptMaterial> receiptMaterialList = receiptMaterialService.list(new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                    .in(WmsOutReceiptMaterial::getWmsOutReceiptId, receiptList.stream().map(WmsOutReceipt::getId).collect(Collectors.toList()))
            );
            for(WmsOutReceiptTaskPick pick:pickList){
                //用出库任务物料id进行匹配
                boolean anyMatch = receiptMaterialList.stream().anyMatch(o -> pick.getWmsOutReceiptTaskMaterialId().equals(o.getWmsOutReceiptTaskMaterialId()));
                if(anyMatch){
                    String errorMessage="已在出库的单中无法取消拣货，如需取消请从入库单中删除该物料";
                    errorMessage+=",该物料批次号为"+pick.getBatchCode();
                    throw new JeecgBootException(errorMessage);
                }
            }
        }
        // 检查物料是否装车复核
        Boolean needLoadCheckFlag = commonOutboundUtil.needLoadCheckFlag(cancelPickVO.getWmsOutReceiptTaskId());
        if(needLoadCheckFlag){
            // 检查装车复核数据
            for(WmsOutReceiptTaskPick pick:pickList){
                long existCount = loadCheckService.count(new LambdaQueryWrapper<WmsOutReceiptLoadCheck>()
                        .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptTaskId, pick.getWmsOutReceiptTaskId())
                        .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptTaskMaterialId, pick.getWmsOutReceiptTaskMaterialId())
                        .eq(WmsOutReceiptLoadCheck::getWmsBasicMaterialId, pick.getWmsBasicMaterialId())
                );
                if(existCount>0){
                    throw new JeecgBootException("存在装车复核的物料，无法取消");
                }
            }
        }
        // 取消拣货
        // 删除拣货数据
        List<String> pickIdList = pickList.stream().map(o -> o.getId()).collect(Collectors.toList());
        this.removeByIds(pickIdList);
        // 更新任务物料的拣货数据
        for(WmsOutReceiptTaskPick pickPo:pickList){
            WmsOutReceiptTaskMaterial taskMaterial = taskMaterialService.getById(pickPo.getWmsOutReceiptTaskMaterialId());
            if(!Objects.isNull(taskMaterial)){
                taskMaterial.setPickQuantity(taskMaterial.getPickQuantity().subtract(pickPo.getPickQuantity()));
                taskMaterialService.updateById(taskMaterial);
            }
        }
    }

    /**
     * 获取出库任务的配置
     * @param taskId
     * @return
     */
    @Override
    public JSONObject getTaskConfig(String taskId) {

        return commonOutboundUtil.getTaskConfig(taskId);
    }

    /**
     * 创建出库单时扫码查询待入库物料(拣货)
     * @param name
     * @param outReceiptTaskId
     * @return
     */
    @Override
    public List<OutboundTaskFullPickVO> getMaterialByNameAndTaskId(String name, String outReceiptTaskId) {
        List<OutboundTaskPickVO> list=pickMapper.listAllPickedByName(outReceiptTaskId, name);
        if(CollectionUtil.isEmpty(list)){
            return Collections.emptyList();
        }else{
            return list.stream().map(pickVO->{
                OutboundTaskFullPickVO outboundTaskFullPickVO=new OutboundTaskFullPickVO();
                WmsOutReceiptTaskMaterial taskMaterial = taskMaterialService.getById(pickVO.getWmsBasicMaterialId());
                if(!Objects.isNull(taskMaterial)){
                    cn.hutool.core.bean.BeanUtil.copyProperties(taskMaterial,outboundTaskFullPickVO);
                }
                cn.hutool.core.bean.BeanUtil.copyProperties(pickVO,outboundTaskFullPickVO);
                return outboundTaskFullPickVO;
            }).collect(Collectors.toList());
        }
    }

    /**
     * 创建出库单时扫码查询待入库物料(未拣货)
     * @param name
     * @param outReceiptTaskId
     * @return
     */
    @Override
    public List<OutboundTaskUnPickVO> getUnPickMaterialByNameAndTaskId(String name, String outReceiptTaskId) {
        List<OutboundTaskUnPickVO> list=pickMapper.listAllUnPickByName(outReceiptTaskId,name);
        if(!CollectionUtil.isEmpty(list)){
            for(OutboundTaskUnPickVO unPickVO:list){
                // 查询即时库存中的库区库位
                RepertorySimpleVO repertorySimpleVO = taskService.getMaterialRepertoryInfoByOutId(unPickVO.getWmsOutReceiptTaskMaterialId());
                unPickVO.setWmsBasicWarehouseId(repertorySimpleVO.getWmsBasicWarehouseId());
                unPickVO.setWmsBasicWarehouseName(repertorySimpleVO.getWmsBasicWarehouseName());
                unPickVO.setWmsBasicWarehouseAreaId(repertorySimpleVO.getWmsBasicWarehouseAreaId());
                unPickVO.setWmsBasicWarehouseAreaName(repertorySimpleVO.getWmsBasicWarehouseAreaName());
                unPickVO.setWmsBasicWarehouseAreaLocationId(repertorySimpleVO.getWmsBasicWarehouseAreaLocationId());
                unPickVO.setWmsBasicWarehouseAreaLocationName(repertorySimpleVO.getWmsBasicWarehouseAreaLocationName());
            }
        }
        return list;
    }

    /**
     * 获取创建移库单流程 提交节点
     * @return
     */
    private BaseFlowDto getMoveBaseFlowDto(){
        //查询移库单流程节点信息
        WorkFlowInfoDto workFlowInfoDto = new WorkFlowInfoDto();
        workFlowInfoDto.setBusinessType("move_type");
        workFlowInfoDto.setDocumentType("Y10");
        List<WmsFlowRecord> wmsFlowRecordList = workFlowService.workFlowInfo(workFlowInfoDto);
        if(CollectionUtil.isEmpty(wmsFlowRecordList)){
            throw new JeecgBootException("查询不到标准移库单流程，无法移库");
        }

        WmsFlowRecord lastFlowRecord = CollectionUtil.getLast(wmsFlowRecordList);
        BaseFlowDto lastFlowDto = new BaseFlowDto();
        lastFlowDto.setCode(lastFlowRecord.getFlowCode());
        lastFlowDto.setBusinessType("move_type");
        lastFlowDto.setDocumentType("Y10");
        return lastFlowDto;
    }


    /**
     * 创建移库单编号
     * @param firstFlowDto
     * @param taskPick
     * @return
     */
    private String createTransferOrder(BaseFlowDto firstFlowDto,WmsOutReceiptTaskPick taskPick){
        //构建移库单数据
        WmsMoveReceiptPage moveData = new WmsMoveReceiptPage();
        moveData.setSysOrgCode(null);
        moveData.setOrganization(null);
        //组织内调拨
        moveData.setTransferType("1");
        moveData.setDocumentCode((String) FillRuleUtil.executeRule("yk_rule", null));
        moveData.setDocumentType(firstFlowDto.getDocumentType());
        //业务组织
        moveData.setOwnerType("1");
        moveData.setBusinessDate(new Date());
        moveData.setTransferFromWarehouseId(taskPick.getTransferWarehouseId());
        moveData.setTransferFromOwner("默认");
        moveData.setWmsBasicWarehouseGroupId("");
        moveData.setWarehouseKeeper("默认");
        moveData.setTransferFromDepartment("默认");
        moveData.setDocumentStatus(null);
        WmsMoveReceiptMaterial materialData=new WmsMoveReceiptMaterial();
        materialData.setSysOrgCode(null);
        materialData.setWmsBasicMaterialId(taskPick.getWmsBasicMaterialId());
        materialData.setBatchCode(taskPick.getBatchCode());
        materialData.setTransferQuantity(taskPick.getPickQuantity());
        materialData.setTransferFromAreaId(taskPick.getWmsBasicWarehouseAreaId());
        materialData.setTransferFromLocationId(taskPick.getWmsBasicWarehouseAreaLocationId());
        materialData.setTransferToAreaId(taskPick.getTransferWarehouseAreaId());
        materialData.setTransferToLocationId(taskPick.getTransferWarehouseAreaLocationId());
        moveData.setWmsMoveReceiptMaterialList(ListUtil.toList(materialData));
        firstFlowDto.setData(moveData);
        //自动创建移库单
        workFlowService.commit( firstFlowDto);
        return moveData.getDocumentCode();
    }


}
